package com.tansun.easycare.rule.datacomponent.service.impl;

import java.io.File;
import java.io.IOException;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tansun.easycare.rule.common.service.impl.RuleBaseServiceImpl;
import com.tansun.easycare.rule.datacomponent.dao.RuleDatacomponentDao;
import com.tansun.easycare.rule.datacomponent.entity.RuleDatacomponent;
import com.tansun.easycare.rule.datacomponent.model.DataComponentEntity;
import com.tansun.easycare.rule.datacomponent.model.DataComponentParam;
import com.tansun.easycare.rule.datacomponent.service.IDataComponentService;
import com.tansun.easycare.rule.datamodel.entity.RuleDataparams;
import com.tansun.easycare.rule.datamodel.entity.RuleDataset;
import com.tansun.easycare.rule.datamodel.model.DataSourceVo;
import com.tansun.easycare.rule.datamodel.service.impl.DataModelServiceImpl;
import com.tansun.easycare.rule.exception.BizException;
import com.tansun.easycare.rule.referencedata.entity.RuleReferenceData;
import com.tansun.easycare.rule.referencedata.service.RuleReferenceDataService;
import com.tansun.easycare.rule.rulemange.entity.RuleManage;
import com.tansun.easycare.rule.rulemange.service.RuleManageService;
import com.tansun.easycare.rule.ruleversion.entity.RuleVersioninfo;
import com.tansun.easycare.rule.ruleversion.service.RuleVersioninfoService;
import com.tansun.rule.common.RuleModelTypeEnum;

@Service
public class DataComponentServiceImpl extends RuleBaseServiceImpl<RuleDatacomponentDao, RuleDatacomponent>
        implements IDataComponentService {

    protected transient Logger logger = LoggerFactory.getLogger(DataComponentServiceImpl.class);
    @Autowired
    private RuleManageService ruleManageService;
    @Autowired
    private RuleVersioninfoService ruleVersioninfoService;
    @Autowired
    private RuleReferenceDataService ruleReferenceDataService;
    @Autowired
    private DataModelServiceImpl dataModelService;

    /**
     * 保存数据源模型
     *
     * @param entity 数据源信息（包含模型信息，数据信息）
     */
    public void saveOrUpdate(DataComponentEntity entity) throws Exception {
        RuleManage ruleManage = entity.getDcModel();
        ruleManage.setStatus("1");
        ruleManage.setModelType(RuleModelTypeEnum.DataComponet.getCode());
        ruleManage = ruleManageService.saveOrUpdate(ruleManage);

        RuleDatacomponent dc = entity.getDatacomponent();
        dc.setProjectCode(ruleManage.getProjectCode());
        dc.setManageId(ruleManage.getId());
        dc.setVersion(ruleManage.getVersion());
        this.save(dc);

        List<Map<String, String>> inMap = (List<Map<String, String>>) (new ObjectMapper()).readValue(dc.getInParams(),
                List.class);
        // 收集引用数据
        Map<String, RuleReferenceData> refMap = new HashMap();
        for (Map<String, String> map : inMap) {
            String paramType = "in";
            String[] keyArr = map.get("paramValue").split("\\.");
            String key = keyArr[0] + "|" + keyArr[1] + "|" + paramType;
            RuleReferenceData item = new RuleReferenceData();
            item.setClassName(keyArr[0]);
            item.setNameen(keyArr[1]);
            item.setDataType(map.get("paramType"));
            ruleReferenceDataService.collectCommonData(item, key, paramType, ruleManage, refMap);
        }
        // 保存数据数据
        this.ruleReferenceDataService.saveReferenceData(refMap);

        String script = generateDc(entity.getDatacomponent());
        RuleVersioninfo ruleVersioninfo = new RuleVersioninfo();
        ruleVersioninfo.init(ruleManage, script);
        this.ruleVersioninfoService.save(ruleVersioninfo);

        DataSourceVo vo = new DataSourceVo();
        RuleDataset rds = new RuleDataset();
        rds.setChzn(entity.getDatacomponent().getEventName());
        rds.setName(entity.getDatacomponent().getEventType());
        List<RuleDataparams> rdplist = new ArrayList<RuleDataparams>();
        List<DataComponentParam> plist1 = JSON.parseArray(entity.getDatacomponent().getInParams(), DataComponentParam.class);
        List<DataComponentParam> plist2 = JSON.parseArray(entity.getDatacomponent().getOutParams(), DataComponentParam.class);
        for (DataComponentParam dcp : plist1) {
            RuleDataparams r = new RuleDataparams();
            r.setChzn(dcp.getParamName());
            r.setName(dcp.getParamKey());
            r.setType(dcp.getParamType());
            r.setLength("on");
            rdplist.add(r);
        }
        for (DataComponentParam dcp : plist2) {
            RuleDataparams r = new RuleDataparams();
            r.setChzn(dcp.getParamName());
            r.setName(dcp.getParamKey());
            r.setType(dcp.getParamType());
            r.setLength("on");
            rdplist.add(r);
        }
        vo.setRds(rds);
        vo.setRdplist(rdplist);
        dataModelService.ToEntity(vo, ruleManage.getProjectCode());
    }

    /**
     * 发布版本
     */
    public void updateVersion(RuleManage ruleManage) throws BizException {
        RuleDatacomponent nodeCon = new RuleDatacomponent();
        if (ruleManage.getOldId() != null) {
            nodeCon.setManageId(ruleManage.getOldId());
        } else
            nodeCon.setManageId(ruleManage.getId());
        nodeCon.setVersion(ruleManage.getOldVersion());
        List<RuleDatacomponent> dcList = this.findList(nodeCon);

        RuleDatacomponent dc = dcList.get(0);
        List<Map<String, String>> inMap = null;
        try {
            inMap = (List<Map<String, String>>) (new ObjectMapper()).readValue(dc.getInParams(), List.class);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        if (inMap == null)
            return;
        // 收集引用数据
        Map<String, RuleReferenceData> refMap = new HashMap();
        for (Map<String, String> map : inMap) {
            String paramType = "in";
            String[] keyArr = map.get("paramValue").split("\\.");
            String key = keyArr[0] + "|" + keyArr[1] + "|" + paramType;
            RuleReferenceData item = new RuleReferenceData();
            item.setClassName(keyArr[0]);
            item.setNameen(keyArr[1]);
            ruleReferenceDataService.collectCommonData(item, key, paramType, ruleManage, refMap);
        }
        // 保存数据数据
        this.ruleReferenceDataService.saveReferenceData(refMap);
        dc.setVersion(ruleManage.getVersion());
        dc.setId(null);
        dc.setManageId(ruleManage.getId());
        this.save(dc);
    }

    /**
     * 模型复制
     */
    @Override
    public void copyRule(RuleManage oldRuleManage, RuleManage ruleManage) throws BizException {
        ruleManage.setOldVersion(oldRuleManage.getVersion());
        ruleManage.setOldId(oldRuleManage.getId());
        this.updateVersion(ruleManage);
    }

    /**
     * 查找已发布的规则数据源
     */
    public List<RuleDatacomponent> findPublishList(String projectCode) {
        return this.dao.findPublishList(projectCode);
    }

    private String generateDc(RuleDatacomponent dc) throws Exception {
        String datasourceurl = URLEncoder.encode(dc.getDatasourceurl(), "utf-8");
        String inParams = URLEncoder.encode(dc.getInParams(), "utf-8");
        String eventType = URLEncoder.encode(dc.getEventType(), "utf-8");
        String dataKey = URLEncoder.encode(dc.getDataKey(), "utf-8");
        String dcmethod = "ruleHelper.invokeDC(dataMap,\"%s\",\"%s\",\"%s\",\"%s\");";
        dcmethod = String.format(dcmethod, datasourceurl, eventType, dataKey, inParams);
        return dcmethod;
    }

    /**
     * 从数据网关获取数据
     */
    public String getDataFromGate() throws Exception {
        String path = URLDecoder.decode(DataComponentServiceImpl.class.getResource("/config").getPath(), "UTF-8");
        String newpath = path + "inputjson.json";
        return FileUtils.readFileToString(new File(newpath), "UTF-8");
    }
}
